package com.xncoding.easyexcei.controller;

import cn.idev.excel.EasyExcel;
import cn.idev.excel.ExcelReader;
import cn.idev.excel.FastExcel;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.read.builder.ExcelReaderBuilder;
import cn.idev.excel.read.listener.PageReadListener;
import cn.idev.excel.read.listener.ReadListener;
import cn.idev.excel.read.metadata.ReadSheet;
import cn.idev.excel.util.ListUtils;
import cn.idev.excel.util.MapUtils;
import com.alibaba.fastjson2.JSON;
import com.xncoding.easyexcei.converter.CustomStringStringConverter;
import com.xncoding.easyexcei.listener.ConverterDataListener;
import com.xncoding.easyexcei.listener.DemoDataListener;
import com.xncoding.easyexcei.listener.IndexOrNameDataListener;
import com.xncoding.easyexcei.model.ConverterData;
import com.xncoding.easyexcei.model.DemoData;
import com.xncoding.easyexcei.model.DownloadData;
import com.xncoding.easyexcei.model.IndexOrNameData;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
public class FileController {

    private static final Logger _logger = LoggerFactory.getLogger(FileController.class);

    @RequestMapping("/inportExcel00")
    public void createCsvFileJcTest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            // 使用方式1：Lambda表达式直接处理数据
            FastExcel.read(file.getInputStream(), DemoData.class, new PageReadListener<DemoData>(dataList -> {
                for (DemoData demoData : dataList) {
                    log.info("读取到一条数据: {}", JSON.toJSONString(demoData));
                }
            })).sheet().doRead();

            // 使用方式2：匿名内部类
            FastExcel.read(file.getInputStream(), DemoData.class, new ReadListener<DemoData>() {
                @Override
                public void invoke(DemoData data, AnalysisContext context) {
                    log.info("方式二:读取到一条数据: {}", JSON.toJSONString(data));
                }
                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    log.info("方式二读取结束");
                }
            }).sheet().doRead();

            // 使用方式3：自定义监听器
            FastExcel.read(file.getInputStream(), DemoData.class, new DemoDataListener()).sheet().doRead();

            // 使用方式4：多 Sheet 读取
            try (ExcelReader excelReader = FastExcel.read(file.getInputStream(), DemoData.class, new DemoDataListener()).build()) {
                ReadSheet readSheet = FastExcel.readSheet(0).build();
                excelReader.read(readSheet);
            }

            // 指定列名或列下标读取
            FastExcel.read(file.getInputStream(), IndexOrNameData.class, new IndexOrNameDataListener()).sheet().doRead();
            //多行表头读取
            FastExcel.read(file.getInputStream(), DemoData.class, new DemoDataListener())
                    .sheet()
                    // 设置多行表头的行数，默认为 1
                    .headRowNumber(2)
                    .doRead();
        }


    }


    @RequestMapping("/inportExcel01")
    public void inportExcel01(HttpServletRequest request, HttpServletResponse response) throws IOException {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            // 使用 FastExcel 同步读取 Excel 数据为对象列表
            List<DemoData> list = FastExcel.read(file.getInputStream()).head(DemoData.class).sheet().doReadSync();

            // 处理读取的数据列表
            for (DemoData data : list) {
                log.info("读取到的数据: {}", JSON.toJSONString(data));
            }
        }
    }

    @RequestMapping("/inportExcel02")
    public void inportExcel02(HttpServletRequest request, HttpServletResponse response) throws IOException {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            // 直接读取为 Map 列表
            List<Map<Integer, String>> list = FastExcel.read(file.getInputStream()).sheet().doReadSync();

            // 处理读取的数据列表
            for (Map<Integer, String> data : list) {
                log.info("读取到的数据: {}", JSON.toJSONString(data));
            }
        }
    }
    @RequestMapping("/inportExcel03")
    public void inportExcel03(HttpServletRequest request, HttpServletResponse response) throws IOException {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            // 读取全部 Sheet
            FastExcel.read(file.getInputStream(), DemoData.class, new DemoDataListener()).doReadAll();

            // 读取指定 Sheet
            try (ExcelReader excelReader = FastExcel.read(file.getInputStream()).build()) {
                ReadSheet sheet1 = FastExcel.readSheet(0).head(DemoData.class).registerReadListener(new DemoDataListener()).build();
                ReadSheet sheet2 = FastExcel.readSheet(1).head(DemoData.class).registerReadListener(new DemoDataListener()).build();
                excelReader.read(sheet1, sheet2);
            }
        }
    }
    @RequestMapping("/inportExcel04")
    public void inportExcel04(HttpServletRequest request, HttpServletResponse response) throws IOException {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            // 自定义格式读取
            FastExcel.read(file.getInputStream(), ConverterData.class, new ConverterDataListener())
                    .registerConverter(new CustomStringStringConverter())
                    .sheet().doRead();

        }
    }

    /**
     * 文件下载并且失败的时候返回json（默认失败了会返回一个有部分数据的Excel）
     *
     * @since 2.1.1
     */
    @GetMapping("downloadFailedUsingJson")
    public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            System.out.println(1/0);
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), DownloadData.class).autoCloseStream(Boolean.FALSE).sheet("模板")
                    .doWrite(data());
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = MapUtils.newHashMap();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
        }
    }

    private List<DownloadData> data() {
        List<DownloadData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            DownloadData data = new DownloadData();
            data.setString("字符串" + 0);
            data.setDate(new Date());
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

}
